#include "client.h"
#include "netparam.h"
#include <iostream>
using namespace std;
Client::Client(QObject *parent):QObject(parent),server_conn(NULL)
{
    // setup the monitor
    clientMonitor = new ClientMonitor(NetParams::monitorPort,this);// and let the monitor listening
    clientMonitor->setParent(this);
    connect(clientMonitor,SIGNAL(newConnection(Connection*)),this,SLOT(onNewConnection(Connection*)));
    connect(clientMonitor,SIGNAL(notify(QString,int)),this,SIGNAL(notify(QString,int)));
    connect(this,SIGNAL(notify(QString,int)),SLOT(onNotify(QString,int)));

}

void Client::onSendData(QString ip, QByteArray data)
{
    if(ip.isEmpty() || data.isEmpty())
        return;
    int index = getConnIndex(ip);
    if(index == -1 ) index = tryCreateConnection(ip);
    if (-1 != index)
    {
        conns.at(index)->onSendData(data);// just call,use slot as a normal method
    }
}


void Client::onCloseConnection(QString ip)
{
    qDebug("in client,trying to close %s",ip.toAscii().data());
    if(ip.isEmpty()) return ;
    int i;

    // when connect to self,there are two connections in the conns.
    for(i=0;i<conns.size();i++)
    {
        Connection *conn = conns.at(i);
        if(conn->ipTo == ip)
        {
            conn->close();// abort the connection
            conn->waitForDisconnected();
            conns.remove(i);
            i--;
            // deletelater in connection will free the mem.
        }
    }
    qDebug("leave close");
}


int Client::getConnIndex(QString ip)
{
    if(ip.isEmpty()) return -1;
    int i;
    for(i=0;i<conns.size();i++)
        if(ip == conns.at(i)->ipTo)
            return i;
    return -1;

}
int Client::tryCreateConnection(QString ip)
{
    Connection *conn = new Connection(this);
    appendConnection(conn);
    if(conn->tryConnect(ip,NetParams::monitorPort))
        return conns.size()-1;
    else return -1;
}

void Client::onNewConnection(Connection *conn)
{
    if(conn==NULL)
        return;
    appendConnection(conn);
}

// add the connection,and connect signals:recieve data , notify message
void Client::appendConnection(Connection *conn)
{
    if(conn==NULL) return;
    conns.append(conn);
    connect(conn,SIGNAL(notify(QString,int)),SIGNAL(notify(QString,int)));// connect connection to client
    connect(conn,SIGNAL(recieveData(QString,QByteArray)),SIGNAL(recieveData(QString,QByteArray)));
}

QString Client::getIp()
{
    QString ipAddress;
    QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
    // use the first non-localhost IPv4 address
    for (int i = 0; i < ipAddressesList.size(); ++i) {
        if (ipAddressesList.at(i) != QHostAddress::LocalHost &&
            ipAddressesList.at(i).toIPv4Address()) {
            ipAddress = ipAddressesList.at(i).toString();
            break;
        }
    }
    if (ipAddress.isEmpty())
        ipAddress = QHostAddress(QHostAddress::LocalHost).toString();
    return ipAddress;
}
void Client::onNotify(QString ip, int code)
{
    qDebug("in client,ip:%s,code:%d",ip.toAscii().data(),code);
    onCloseConnection(ip);

}

bool Client::connectToServer()
{
    server_conn = new Connection(this);
    connect(server_conn,SIGNAL(notify(QString,int)),SLOT(onServerNotify(QString,int)));// connect connection to client
    connect(server_conn,SIGNAL(recieveData(QString,QByteArray)),SLOT(onRecieveServerData(QString,QByteArray)));
    return server_conn->tryConnect(NetParams::serverIp,NetParams::serverPort);
}

void Client::onCloseServerConnection()
{
    qDebug("in client,close server connection");
    if(server_conn == NULL) return;
    server_conn->abort();
    server_conn = NULL;
}
void Client::onSendServerData(QByteArray data)
{
    qDebug("in client,send data to server");
    if(server_conn!=NULL || connectToServer())
        server_conn->onSendData(data);

}
void Client::onRecieveServerData(QString ip, QByteArray data)
{
    emit recieveServerData(data);// just to emit the server signal
}
void Client::onServerNotify(QString ip, int code)
{
    qDebug("in client ,get notify %d from server",code);
    emit serverNotify(code);
    onCloseServerConnection();
}


